<template>
  <div class="graph">
    <graph-opt :graph="graph" />
    <div id="container">
      <graph-stencil id="stencil" @onStartDrag="startDrag" />
      <div id="graph-container"></div>
    </div>
  </div>
</template>

<script setup>
import { onMounted, ref } from 'vue';
import { useRoute } from 'vue-router';
import { Graph, Shape } from '@antv/x6';
import { Stencil } from '@antv/x6-plugin-stencil'; // 如果使用 stencil 功能，需要安装此包
import { Transform } from '@antv/x6-plugin-transform'; // 如果使用图形变换功能，需要安装此包
import { Selection } from '@antv/x6-plugin-selection'; // 如果使用框选功能，需要安装此包
import { Snapline } from '@antv/x6-plugin-snapline'; // 如果使用对齐线功能，需要安装此包
import { Keyboard } from '@antv/x6-plugin-keyboard'; //如果使用快捷键功能，需要安装此包
import { Clipboard } from '@antv/x6-plugin-clipboard'; // 如果使用剪切板功能，需要安装此包
import { History } from '@antv/x6-plugin-history'; // 如果使用撤销重做功能，需要安装此包
import GraphOpt from './components/GraphOpt.vue';
import GraphStencil from './components/GraphStencil.vue';
import { startDragToGraph } from './drag';
const route = useRoute();
const graph = ref(null);
onMounted(() => {
  init();
});
//获得历史记录值
if (route.query.cells) {
  setTimeout(() => graph.value?.fromJSON(JSON.parse(route.query.cells)), 0);
}
const init = () => {
  // #region 初始化画布
  graph.value = new Graph({
    container: document.getElementById('graph-container'),
    //画布网格
    grid: true,
    //移动画布
    panning: true,
    //鼠标缩放画布
    mousewheel: {
      enabled: true,
      zoomAtMousePosition: true,
      modifiers: 'ctrl',
      minScale: 0.5,
      maxScale: 3,
    },
    //连线交互
    connecting: {
      router: 'manhattan',
      connector: {
        name: 'rounded',
        args: {
          radius: 8,
        },
      },
      anchor: 'center',
      connectionPoint: 'anchor',
      allowBlank: false,
      allowNode: false,
      snap: {
        radius: 20,
      },
      createEdge() {
        return new Shape.Edge({
          attrs: {
            line: {
              stroke: '#A2B1C3',
              strokeWidth: 2,
              targetMarker: {
                name: 'block',
                width: 12,
                height: 8,
              },
            },
          },
          zIndex: 0,
        });
      },
      validateConnection({ targetMagnet }) {
        return !!targetMagnet;
      },
    },
    highlighting: {
      magnetAdsorbed: {
        name: 'stroke',
        args: {
          attrs: {
            fill: '#5F95FF',
            stroke: '#5F95FF',
          },
        },
      },
    },
  });
  // #region 使用插件
  graph.value
    .use(
      new Transform({
        resizing: true,
        rotating: true,
      }),
    )
    .use(
      new Selection({
        rubberband: true,
        showNodeSelectionBox: true,
      }),
    )
    .use(new Snapline())
    .use(new Keyboard())
    .use(new Clipboard())
    .use(new History());
  // #endregion

  // delete
  graph.value.bindKey('backspace', () => {
    const cells = graph.value.getSelectedCells();
    if (cells.length) {
      graph.value.removeCells(cells);
    }
  });
  // 控制连接桩显示/隐藏
  const showPorts = (ports, show) => {
    for (let i = 0, len = ports.length; i < len; i += 1) {
      ports[i].style.visibility = show ? 'visible' : 'hidden';
    }
  };
  graph.value.on('node:mouseenter', () => {
    const container = document.getElementById('graph-container');
    const ports = container.querySelectorAll('.x6-port-body');
    showPorts(ports, true);
  });
  graph.value.on('node:mouseleave', () => {
    const container = document.getElementById('graph-container');
    const ports = container.querySelectorAll('.x6-port-body');
    showPorts(ports, false);
  });
};
const startDrag = (shape, e) => {
  startDragToGraph(graph.value, shape, e);
};
</script>
<style lang="less" scoped>
.graph {
  position: relative;

  #container {
    display: flex;
    width: 100%;
    height: calc(100vh - 60px);
    border: 1px solid #dfe3e8;
  }

  #stencil {
    position: relative;
    width: 180px;
    height: 100%;
    border-right: 1px solid #dfe3e8;
  }

  #graph-container {
    width: calc(100% - 180px);
    height: 100%;
  }
}
</style>
